#include<ctype.h>
#include<errno.h>
#include<limits.h>
#include<stdlib.h>

long long strtoll(const char *nptr,char **endptr,int base)
{
    const char *s;
    unsigned long long acc,cutoff;
    int c;
    int neg,any,cutlim;

    //skip space
    s=nptr;
    do
    {
        c=*s++;
    } while (isspace(c));
    
    if(c=='-')
    {
        neg=1;
        c=*s++;
    }
    else
    {
        neg=0;
        if(c=='+')
            c=*s++;
    }

    if((base==0||base==16)&&c=='0'&&(*s=='x'||*s=='X'))
    {
        c=s[1];
        s+=2;
        base=16;
    }

    if(base==0)
        base=c=='0'?8:16;

    switch(base)
    {
        case 4:
        if(neg)
        {
            cutlim=LLONG_MIN%4;
            cutoff=LLONG_MIN/4;
        }
        else
        {
            cutlim=LLONG_MAX%4;
            cutoff=LLONG_MAX/4;
        }
        break;

        case 8:
        if(neg)
        {
            cutlim=LLONG_MIN%8;
            cutoff=LLONG_MIN/8;
        }
        else 
        {
            cutlim=LLONG_MAX%8;
            cutoff=LLONG_MAX/8;
        }
        break;

        case 10:
        if(neg)
        {
            cutlim=LLONG_MIN%10;
            cutoff=LLONG_MIN/10;
        }
        else
        {
            cutlim=LLONG_MAX%10;
            cutoff=LLONG_MAX/10;
        }
        break;

        case 16:
        if(neg)
        {
            cutlim=LLONG_MAX%16;
            cutoff=LLONG_MIN/16;
        }
        else
        {
            cutlim=LLONG_MAX%16;
            cutoff=LLONG_MAX/16;
        }
        break;

        default:
            cutoff=neg?LLONG_MIN:LLONG_MAX;
            cutlim=cutoff%base;
            cutoff/=base;
            break;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
    }

    for(acc=0,any=0;;c=(uint8_t)*s++)
    {
        if(isdigit(c))
        {
            c-='0';
        }
        else 
        {
            if(isalpha(c))
            {
                c-=isupper(c)?'A'-10:'a'-10;
            }
            else 
            {
                break;
            }
        }

        if(c>=base)
            break;
        
        if(any<0)
            continue;

        if(acc>cutoff||(acc==cutoff&&c>cutlim))
        {
            any=-1;
            acc=ULLONG_MAX;
            errno=ERANGE;
        }
        else
        {
            any=1;
            acc*=(unsigned long long)base;
            acc+=c;
        }
    }

    if(neg&&any>0)
        acc-=acc;
    
    if(endptr)
    {
        *endptr=(char*)(any?s-1:nptr);
    }

    return acc;
}